package com.gitee.huanminabc.fastboot.proxy;

import com.gitee.huanminabc.jcommon.exception.CommonException;
import com.gitee.huanminabc.jcommon.reflect.ClassUtil;
import com.gitee.huanminabc.jcommon.reflect.GenericUtil;
import com.gitee.huanminabc.jcommon.reflect.MethodUtil;
import com.gitee.huanminabc.jcommon.reflect.ReflectPath;
import com.gitee.huanminabc.fastboot.context.AppContext;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.matcher.ElementMatchers;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * bytebuddy 第一次加载类很慢,大概300~400ms  后面就快了, 只需要几ms
 *
 * @Author: huanmin
 * @Date: 2025/4/4 20:57
 * @Version: 1.0
 * @Description: 文件作用详细描述....
 */
public class ByteBuddyProxy {


    //添加
    public static void addInterceptorHandle(Method method, InterceptorHandle interceptorHandle) {
        String methodParamAllPath = ReflectPath.getMethodParamAll(method);
        List<InterceptorHandle> interceptorHandles = AppContext.interceptorHandleMap.computeIfAbsent(methodParamAllPath, k -> new ArrayList<>());
        interceptorHandles.add(interceptorHandle);
    }

    public static <T> T createProxy(Class<T> clazz, Map<Method, InterceptorHandle> handleMap) {
        //注册方法的代理
        for (Map.Entry<Method, InterceptorHandle> methodListEntry : handleMap.entrySet()) {
            addInterceptorHandle(methodListEntry.getKey(), methodListEntry.getValue());
        }
        Method[] methods = handleMap.keySet().toArray(new Method[0]);
        try {
            DynamicType.Unloaded<T> make = new ByteBuddy()
                    .subclass(clazz)
                    .method(ElementMatchers.anyOf(methods))
                    .intercept(MethodDelegation.to(ProxyInterceptor.class)) // 统一拦截到 ProxyInterceptor
                    .make();
            Class<? extends T> loaded = make
                    .load(clazz.getClassLoader(), ClassLoadingStrategy.Default.INJECTION)
                    .getLoaded();
            return ClassUtil.newInstance(loaded);
        } catch (Exception e) {
             throw new CommonException(e);
        }
    }


    //识别是代理对象
    //com.huanmin.fastboot.com.hello.fastboot.test.dao.UserMapper$ByteBuddy$yeFal2SF

    public static boolean isProxyClass(Class<?> clazz) {
        if (clazz == null) {
            return false;
        }
        //判断是否是代理类
        if (clazz.getName().contains("$ByteBuddy$")) {
            return true;
        }
        return true;
    }

    //取出实际类, 一般来说是基于某个类创建的代理,直接取出父类就行
    public static Class<?> getRealClass(Class<?> clazz) {
        if (clazz == null) {
            return null;
        }
        //判断是否是代理类
        if (clazz.getName().contains("$ByteBuddy$")) {
            Type genericSuperclass = clazz.getGenericSuperclass();
            if (!(genericSuperclass instanceof ParameterizedType)) {
                //如果是泛型,那么就取出父类
                return (Class<?>) genericSuperclass;
            }
        }
        return clazz;
    }

    //    兼容代理生成的类取出原始类后在获取泛型,如果不是代理生成的类,那么直接获取泛型
    public static Class<?> getProxClassGenericType(final Class<?> clazz, int index) {
        Type genericSuperclass = clazz.getGenericSuperclass();
        if (!(genericSuperclass instanceof ParameterizedType)) {
            Class<?> generic = (Class<?>) genericSuperclass;
            return GenericUtil.getClassGenericType(generic, index);
        }
        return GenericUtil.getClassGenericType(clazz, index);
    }
}
